
#ifndef I2C_PROTOCOL_H
#define I2C_PROTOCOL_H 

#define RETURN_OK		0
#define RETURN_FAIL		-1
//规定所有的返回值依照上面的规则

typedef enum{
	IN_MODE,
	OUT_MODE,
}gpio_direction;

typedef enum{
	LOW_LEVEL,
	HIGH_LEVEL,
}gpio_level;

typedef enum{
	PULL_NO,
	PULL_DOWN,
	PULL_UP,
}gpio_pullupdn;

typedef enum{
	LOG_NONE,		/*!< No log output */
	LOG_ERROR,		/*!< Critical errors, software module can not recover on its own */
	LOG_WARN,		/*!< Error conditions from which recovery measures have been taken */
	LOG_INFO,		/*!< Information messages which describe normal flow of events */
	LOG_DEBUG,		/*!< Extra information which is not necessary for normal use (values, pointers, sizes, etc). */
	//LOG_VERBOSE,	/*!< Bigger chunks of debugging information, or frequent messages which can potentially flood the output. */
}i2c_print_level;

#define LOG_COLOR_BLACK   "30"
#define LOG_COLOR_RED     "31"
#define LOG_COLOR_GREEN   "32"
#define LOG_COLOR_BROWN   "33"
#define LOG_COLOR_BLUE    "34"
#define LOG_COLOR_PURPLE  "35"
#define LOG_COLOR_CYAN    "36"
#define LOG_COLOR(COLOR)  "\033[0;" COLOR "m"
#define LOG_BOLD(COLOR)   "\033[1;" COLOR "m"
#define LOG_RESET_COLOR   "\033[0m"
#define LOG_COLOR_E       LOG_COLOR(LOG_COLOR_RED)
#define LOG_COLOR_W       LOG_COLOR(LOG_COLOR_BROWN)
#define LOG_COLOR_I       LOG_COLOR(LOG_COLOR_GREEN)
#define LOG_COLOR_D

int i2c_log_write(i2c_print_level level, char *format, ...);

#define LOG_FORMAT(letter, format)  LOG_COLOR_ ## letter format LOG_RESET_COLOR "\n"
#define i2c_log_print(level, format, ...)	do {	\
	if(level == LOG_ERROR)	{i2c_log_write(level, LOG_FORMAT(E, format), ##__VA_ARGS__);}	\
	if(level == LOG_WARN)	{i2c_log_write(level, LOG_FORMAT(W, format), ##__VA_ARGS__);}	\
	if(level == LOG_INFO)	{i2c_log_write(level, LOG_FORMAT(I, format), ##__VA_ARGS__);}	\
	else					{i2c_log_write(level, LOG_FORMAT(D, format), ##__VA_ARGS__);}	\
}while(0)
//方法1--》直接给级别
//#define i2c_print(level, format, ...)	i2c_log_print(level, format, ##__VA_ARGS__)
//方法2--》给出函数，这个应该比较好一点
#define I2C_LOGE(format, ...)	i2c_log_print(LOG_ERROR, format, ##__VA_ARGS__)
#define I2C_LOGW(format, ...)	i2c_log_print(LOG_WARN, format, ##__VA_ARGS__)
#define I2C_LOGI(format, ...)	i2c_log_print(LOG_INFO, format, ##__VA_ARGS__)
#define I2C_LOGD(format, ...)	i2c_log_print(LOG_DEBUG, format, ##__VA_ARGS__)

#define i2c_ASSERT(a) if (!(a)) {                                 \
	I2C_LOGE("%s:%d (%s)- assert failed!\n", __FILE__, __LINE__,  \
			__FUNCTION__);											\
}

#define CHECK_ERROR(a) do {																		\
	int err_ret = (a);																			\
	if(err_ret < RETURN_OK){																	\
		I2C_LOGE("Wrong return:%d in function:%s, line:%d\n", err_ret, __FUNCTION__, __LINE__);	\
	}																							\
}while(0);

typedef struct{
	uint8 gpio_scl;
	uint8 gpio_sda;
}i2c_gpio, *Pi2c_gpio;

//malloc
//print
//free
//don't need task creat
//amd sem didn't need
//delay
//set gpio direction
//set gpio level
//get gpio level
//set pullup pulldown

//success > 0, fail <= 0
typedef void* (*I2C_MALLOC)(uint32 size);
typedef int  (*I2C_FREE)(void *ptr);
//typedef void (*I2C_PRINT)();
//typedef int  (*I2C_PRINT)(int8 *format, ...);
typedef int  (*I2C_DELAYUS)(uint32 time_us);
typedef int  (*I2C_SET_GPIO_DIRECTION)(int gpio, uint8 direction);
typedef int  (*I2C_SET_GPIO_LEVEL)(int gpio, uint8 value);
typedef int  (*I2C_GET_GPIO_LEVEL)(int gpio);
typedef void (*I2C_SET_GPIO_PULLUPDOWN)(int gpio, int pullupdown);

//typedef CHECK_IS_NUL(a)	{if(!a)print("A is NULL!\n");};

typedef struct{
	I2C_MALLOC malloc;
	I2C_FREE   free;
	//I2C_PRINT  log_print;
	I2C_DELAYUS  delay;
	I2C_SET_GPIO_DIRECTION set_gpio_direction;
	I2C_SET_GPIO_LEVEL set_gpio_level;
	I2C_GET_GPIO_LEVEL get_gpio_level;
	I2C_SET_GPIO_PULLUPDOWN set_gpio_pullupdn;
}i2c_callback, *Pi2c_callback;

int i2c_init(Pi2c_gpio gpio, Pi2c_callback cb, i2c_print_level log_level);
void i2c_send_buf(uint8 addr, uint8 *buf, uint8 buf_len);
void i2c_read_buf(uint8 addr, uint8 *buf, uint8 buf_len);
void i2c_send_reg_buf(uint8 addr, uint8 reg, uint8 *buf, uint8 buf_len);
void i2c_read_reg_buf(uint8 addr, uint8 reg, uint8 *buf, uint8 buf_len);
int8 i2c_start(void);
int8 i2c_stop();
void i2c_deinit(void);

#endif /* I2C_PROTOCOL_H */



